//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include "utils.h"
#include "logicmanager.h"
#include "../common/MarkupSTL.h"
#include "vigorshellcmdprocessor.h"

CVigorShellCmdProcessor::CVigorShellCmdProcessor(CLinkGuard& link):m_link(link)
{
}

CVigorShellCmdProcessor::~CVigorShellCmdProcessor(void)
{
}

void CVigorShellCmdProcessor::Initialize()
{
}

RTSTRING CVigorShellCmdProcessor::GetCaps()
{
	CMarkupSTL	doc;
	doc.AddElem( SHELL_CAPS_EL );

	doc.AddAttrib( GLOBAL_NAME_ATR,		"Vigor" );

	doc.AddAttrib( SHELL_SCRIPT_FORMAT,	SCRIPT_FORMAT_XML_VAL );
	doc.AddAttrib( SHELL_MAC_FILTER,	GLOBAL_ENABLE_VAL );
	doc.AddAttrib( SHELL_PING,			GLOBAL_ENABLE_VAL );
	doc.AddAttrib( SHELL_PORT_FORWARD,	GLOBAL_ENABLE_VAL );
	doc.AddAttrib( SHELL_BANDWIDTH,		GLOBAL_ENABLE_VAL );
	doc.AddAttrib( SHELL_CONNECTIONS,	GLOBAL_ENABLE_VAL );
	doc.AddAttrib( SHELL_TCPNAT_SETTNGS,GLOBAL_DISABLE_VAL );
	doc.AddAttrib( SHELL_PROCKILL,		GLOBAL_DISABLE_VAL );
	doc.AddAttrib( SHELL_SYSLOGCONFIG,	GLOBAL_ENABLE_VAL );
	doc.AddAttrib( SHELL_KERNELMOD,		GLOBAL_DISABLE_VAL );

	doc.AddAttrib( SHELL_NAT_USAGE,		GLOBAL_DISABLE_VAL );
	doc.AddAttrib( SHELL_MEM_USAGE,		GLOBAL_DISABLE_VAL );
	doc.AddAttrib( SHELL_CPU_USAGE,		GLOBAL_DISABLE_VAL );
	doc.AddAttrib( SHELL_RT_USAGE,		GLOBAL_DISABLE_VAL );

	return doc.GetDoc();
}

void CVigorShellCmdProcessor::DispatchCmd(const COMMANDREQUEST& cmd, COMMANDRESPONSE& cmdOut,	bool& bNotify)
{
	bNotify = false;

	cmdOut.code = cmd.code;
	cmdOut.subCode = cmd.subCode;

	switch( cmd.code )
	{
		case cCmdScript:
			OnExecuteScript( cmd.strScript, cmdOut, bNotify);
		break;

		//Not supported
		case cCmdConntracMax:
		case cCmdGetSlabTable:
		case cCmdMemMax:
		case cCmdMemVal:
		case cCmdRTCacheMax:
		case cCmdRTCacheVal:
		case cCmdGetTCPTimeOuts:
		break;

		case cCmdGetRouterID:
			OnGetRouterID( cmdOut, bNotify);
		break;

		case cCmdGetVersion:
			OnGetVersion( cmdOut, bNotify);
		break;

		case cCmdGetRouterWANAddress:
			OnGetRouterWANAddress( cmdOut, bNotify);
		break;

		case cCmdConntrTableEntries:
			OnGetConntracTableEnt( cmdOut, bNotify);
		break;

		case cCmdInterfaceStat:
			OnGetInterfaceStat( cmdOut, bNotify);
		break;

		default:
		{
			//assert(0);
		}
		break;
	}
}

/////////////////////////////////////////////////////////////////////////////////////
//CMD Handlers
void CVigorShellCmdProcessor::OnExecuteScript(const wxString& strScript, COMMANDRESPONSE& cmdOut,
											  bool& bNotify)
{

}

void CVigorShellCmdProcessor::OnGetRouterID(COMMANDRESPONSE& cmdOut, bool& bNotify)
{
	cmdOut.lData = CODE_GET_MAC_FAIL;

	RTSTRING strData;
	wxString strMAC;

	//Get Mac from eth0
	int nTry(1);

	do
	{
		strData = m_link->SendCmd("sys iface");

		size_t tPos = strData.find("MAC:");

		if ( std::string::npos != tPos )
		{
			strData.erase(0, tPos+4); //MAC:

			strMAC = ExtractMACFromString( wxString::FromAscii(strData.c_str()), wxT('-') );

			if ( strMAC.empty() )
			{
				strMAC = ExtractMACFromString( wxString::FromAscii(strData.c_str()));
			}
		}
	}
	while(nTry-->0 && strMAC.empty() );

	if ( strMAC.empty() )
	{
		cmdOut.strData = (const char*)strMAC.ToAscii();
		cmdOut.lData = CODE_GET_MAC_FAIL;
		bNotify = true;
	}
	else
	{
		cmdOut.strData = (const char*)strMAC.ToAscii();
		cmdOut.lData = CODE_GET_MAC_OK;
		bNotify = true;
	}
}

void CVigorShellCmdProcessor::OnGetVersion(COMMANDRESPONSE& cmdOut, bool& bNotify)
{
	RTSTRING strData = m_link->SendCmd(wxT("sys version"));

	if ( !strData.empty() )
	{
		cmdOut.strData = strData;
		bNotify = true;
	}
}

/*
DHCP Client Status:

DHCP Server IP : 0.0.0.0
WAN IP         : 0.0.0.0
WAN Netmask    : 0.0.0.0
WAN Gateway    :
Primary DNS    :
Secondary DNS  :
Leased Time    : 0
Leased Time T1 : 0
Leased Time T2 : 0
Leased Elapsed : 0
Leased Elapsed T1: 0
Leased Elapsed T2: 0
*/
void CVigorShellCmdProcessor::OnGetRouterWANAddress(COMMANDRESPONSE& cmdOut, bool& bNotify)
{
	RTSTRING strData = m_link->SendCmd(wxT("ip dhcp status"));

	if ( !strData.empty() )
	{
		RTSTRING strLine = CLogicManager::GetStringWithPattern(strData,  "WAN IP", true);
		RTSTRING strIP   = ExtractIPFromString( wxString::FromAscii(strLine.c_str()) );
		cmdOut.strData = strIP;
		bNotify = true;
	}
}

/*
NAT Port Redirection Running Table:

Index  Protocol  Public Port   Private IP        Private Port
 1            0            0   0.0.0.0                      0
 2            0            0   0.0.0.0                      0
 3            0            0   0.0.0.0                      0
 4            0            0   0.0.0.0                      0
 5            0            0   0.0.0.0                      0
 6            0            0   0.0.0.0                      0

 Protocol: 0 = Disable, 6 = TCP, 17 = UDP
 */

bool NATFilter(TABLEROW& row)
{
	bool bRes(false);

	if ( 5 == row.size() && !row[0].empty() && !row[1].empty() )
	{
		bRes = isdigit(row[0][0])
			#ifndef _DEBUG
			&& row[1]!="0"
			#endif
			;
	}

	return bRes;
}

void CVigorShellCmdProcessor::OnGetConntracTableEnt(COMMANDRESPONSE& cmdOut, bool& bNotify)
{
	cmdOut.subCode = cCmdSubCodeXML;

	RTSTRING strData = ReadVigorPagedData( wxT("show nat") );

	if ( !strData.empty() )
	{
		PROCTABLEWITHHEADER table = CLogicManager::ParseTable( strData, NATFilter);

		if ( !table.empty() )
		{
			CMarkupSTL	doc;
			doc.AddElem( CONLIST_ROOT_EL );

			for(size_t i=0;i<table.size();i++)
			{
				doc.AddChildElem( GLOBAL_ENTRY_EL);

				wxString strProto = CLogicManager::GeValFromTable(table, 1, i);
				std::string strProtoVal(CONLIST_PROTO_UNK_VAL);

				if ( wxT("TCP")==strProto )
				{
					strProtoVal = CONLIST_PROTO_TCP_VAL;
				}
				else
				if ( wxT("UDP")==strProto )
				{
					strProtoVal = CONLIST_PROTO_UDP_VAL;
				}

				doc.AddChildAttrib(CONLIST_PROTO_ATTR, strProtoVal.c_str());

				wxString strPublicPort = CLogicManager::GeValFromTable(table, 2, i);
				doc.AddChildAttrib(CONLIST_DST_PORT_ATTR, strPublicPort.ToAscii());

				wxString strPrivateIP = CLogicManager::GeValFromTable(table, 3, i);
				doc.AddChildAttrib(CONLIST_SRC_IP_ATTR, strPrivateIP.ToAscii());

				wxString strPrivatePort = CLogicManager::GeValFromTable(table, 4, i);
				doc.AddChildAttrib(CONLIST_SRC_PORT_ATTR, strPrivatePort.ToAscii());
			}

			cmdOut.strXML = doc.GetDoc();
			bNotify = true;
		}
	}
}

//per interface statistics missed?
void CVigorShellCmdProcessor::OnGetInterfaceStat(COMMANDRESPONSE& cmdOut, bool& bNotify)
{
}







////////////////////////////////////////////////////////////////////////////////////////////////
//UTL

//--- MORE ---   ['q': Quit, 'Enter': New Lines, 'Space Bar': Next Page] ---

RTSTRING CVigorShellCmdProcessor::ReadVigorPagedData( const wxString& strCMD )
{
	RTSTRING strRes;
	RTSTRING strData = m_link->SendCmd(strCMD);

	do
	{
		size_t tPos = strData.find("--- MORE");

		if ( std::string::npos!=tPos )
		{
			strData.erase(tPos);
			strRes+=strData;

			strData = m_link->SendSymb(" ");
		}
		else
		{
			strRes+=strData;
			break;
		}

	}while( !strData.empty() );

	return strRes;
}
